#!/bin/bash

# Ubuntu下释放3003端口的脚本
# 用于杀死占用3003端口的进程

set -e

# 配置变量
PORT=3003
PROCESS_NAME=""

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查是否为root用户
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_warning "建议使用root权限运行此脚本"
        log_info "可以使用: sudo $0"
    fi
}

# 检查端口占用
check_port() {
    log_info "检查端口 $PORT 的占用情况..."
    
    # 使用netstat检查
    if command -v netstat &> /dev/null; then
        PROCESS_INFO=$(netstat -tlnp 2>/dev/null | grep ":$PORT " || true)
    elif command -v ss &> /dev/null; then
        PROCESS_INFO=$(ss -tlnp 2>/dev/null | grep ":$PORT " || true)
    else
        log_error "未找到netstat或ss命令"
        exit 1
    fi
    
    if [[ -z "$PROCESS_INFO" ]]; then
        log_success "端口 $PORT 当前没有被占用"
        return 0
    else
        log_warning "端口 $PORT 被以下进程占用："
        echo "$PROCESS_INFO"
        return 1
    fi
}

# 获取占用端口的进程信息
get_process_info() {
    log_info "获取占用端口 $PORT 的进程详细信息..."
    
    # 使用lsof获取进程信息
    if command -v lsof &> /dev/null; then
        PROCESS_INFO=$(lsof -i :$PORT 2>/dev/null || true)
        if [[ -n "$PROCESS_INFO" ]]; then
            echo "$PROCESS_INFO"
            return 0
        fi
    fi
    
    # 使用fuser获取进程信息
    if command -v fuser &> /dev/null; then
        PROCESS_INFO=$(fuser $PORT/tcp 2>/dev/null || true)
        if [[ -n "$PROCESS_INFO" ]]; then
            echo "进程ID: $PROCESS_INFO"
            return 0
        fi
    fi
    
    # 使用netstat获取进程信息
    if command -v netstat &> /dev/null; then
        PROCESS_INFO=$(netstat -tlnp 2>/dev/null | grep ":$PORT " || true)
        if [[ -n "$PROCESS_INFO" ]]; then
            echo "$PROCESS_INFO"
            return 0
        fi
    fi
    
    log_error "无法获取进程信息"
    return 1
}

# 杀死占用端口的进程
kill_process() {
    log_info "尝试杀死占用端口 $PORT 的进程..."
    
    # 使用fuser杀死进程
    if command -v fuser &> /dev/null; then
        log_info "使用fuser杀死进程..."
        if fuser -k $PORT/tcp 2>/dev/null; then
            log_success "使用fuser成功杀死进程"
            return 0
        fi
    fi
    
    # 使用lsof获取PID并杀死
    if command -v lsof &> /dev/null; then
        log_info "使用lsof获取PID并杀死进程..."
        PIDS=$(lsof -ti :$PORT 2>/dev/null || true)
        if [[ -n "$PIDS" ]]; then
            for PID in $PIDS; do
                log_info "杀死进程 PID: $PID"
                if kill -9 "$PID" 2>/dev/null; then
                    log_success "成功杀死进程 PID: $PID"
                else
                    log_warning "无法杀死进程 PID: $PID"
                fi
            done
            return 0
        fi
    fi
    
    # 使用netstat获取PID并杀死
    if command -v netstat &> /dev/null; then
        log_info "使用netstat获取PID并杀死进程..."
        PIDS=$(netstat -tlnp 2>/dev/null | grep ":$PORT " | awk '{print $7}' | cut -d'/' -f1 | grep -E '^[0-9]+$' || true)
        if [[ -n "$PIDS" ]]; then
            for PID in $PIDS; do
                log_info "杀死进程 PID: $PID"
                if kill -9 "$PID" 2>/dev/null; then
                    log_success "成功杀死进程 PID: $PID"
                else
                    log_warning "无法杀死进程 PID: $PID"
                fi
            done
            return 0
        fi
    fi
    
    log_error "无法杀死占用端口的进程"
    return 1
}

# 验证端口是否已释放
verify_port_release() {
    log_info "验证端口 $PORT 是否已释放..."
    
    sleep 2
    
    if check_port; then
        log_success "端口 $PORT 已成功释放"
        return 0
    else
        log_error "端口 $PORT 仍然被占用"
        return 1
    fi
}

# 显示帮助信息
show_help() {
    echo "Ubuntu下释放3003端口的脚本"
    echo ""
    echo "用法: $0 [选项]"
    echo ""
    echo "选项:"
    echo "  -p, --port PORT    指定要释放的端口 (默认: 3003)"
    echo "  -f, --force        强制杀死进程"
    echo "  -v, --verbose      详细输出"
    echo "  --help             显示此帮助信息"
    echo ""
    echo "示例:"
    echo "  $0                  # 释放端口3003"
    echo "  $0 -p 8080         # 释放端口8080"
    echo "  $0 -f              # 强制释放端口"
    echo ""
    echo "注意: 建议使用root权限运行以获得最佳效果"
}

# 解析命令行参数
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -p|--port)
                PORT="$2"
                shift 2
                ;;
            -f|--force)
                FORCE=true
                shift
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            --help)
                show_help
                exit 0
                ;;
            *)
                log_error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
    done
}

# 主函数
main() {
    log_info "开始释放端口 $PORT..."
    
    # 解析命令行参数
    parse_args "$@"
    
    # 检查权限
    check_root
    
    # 检查端口占用
    if check_port; then
        log_success "端口 $PORT 当前没有被占用，无需释放"
        exit 0
    fi
    
    # 显示进程信息
    get_process_info
    
    # 询问用户是否继续
    if [[ "$FORCE" != true ]]; then
        echo ""
        read -p "是否继续杀死占用端口的进程? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "操作已取消"
            exit 0
        fi
    fi
    
    # 杀死进程
    if kill_process; then
        # 验证端口是否已释放
        if verify_port_release; then
            log_success "端口 $PORT 释放成功！"
        else
            log_error "端口 $PORT 释放失败"
            exit 1
        fi
    else
        log_error "无法释放端口 $PORT"
        exit 1
    fi
}

# 运行主函数
main "$@"
